home *** CD-ROM | disk | FTP | other *** search
/ PC Basics 53 / PC Basics Issue 53.iso / Software / Internet / Invboard.exe / PC Basics 53 / Invboard / upload / sources / Search.php < prev    next >
Encoding:
PHP Script  |  2002-06-12  |  30.9 KB  |  1,050 lines

  1. <?php
  2.  
  3. /*
  4. +--------------------------------------------------------------------------
  5. |   IBFORUMS v1
  6. |   ========================================
  7. |   by Matthew Mecham and David Baxter
  8. |   (c) 2001,2002 IBForums
  9. |   http://www.ibforums.com
  10. |   ========================================
  11. |   Web: http://www.ibforums.com
  12. |   Email: phpboards@ibforums.com
  13. |   Licence Info: phpib-licence@ibforums.com
  14. +---------------------------------------------------------------------------
  15. |
  16. |   > Searching procedures
  17. |   > Module written by Matt Mecham
  18. |   > Date started: 24th February 2002
  19. |
  20. |    > Module Version Number: 1.0.0
  21. +--------------------------------------------------------------------------
  22. |
  23. |   MODULE NOTES:
  24. |   -------------
  25. |
  26. |   I've been deliberating whether we should implement some kind of WORD ID / 
  27. |   search logging table for index.
  28. |   iB3 PERL had such a feature, but that was to aide the DBM searches, which
  29. |   were slow at best.
  30. |   The biggest complaint we had was that adding a word ID / search logging table
  31. |   effectively doubled the amount of space needed in the mySQL database. I've seen
  32. |   this complaint echo'd on the support boards of other forum software.
  33. |   The other downside to such a feature would be the overhaul needed to update it
  34. |   with new posts/topics and topic movement / deletion.
  35. |  
  36. |   I figure that people post more than they search, so a full table scan once per
  37. |   search request is offset against the CPU to keep the search log tables up to date
  38. |
  39. |   I'm going to stick my neck out and go the full table scan route. It's not as effecient
  40. |   as a search table would be, but the benefits include no overhead updating it, and a smaller
  41. |   overall DB size - which is vital to some people on certain hosts.
  42. |
  43. |   This may change if it becomes apparent that it's not very efficient in the long run
  44. +--------------------------------------------------------------------------
  45. */
  46.  
  47. // 
  48.  
  49. $idx = new Search;
  50.  
  51. class Search {
  52.  
  53.     var $output     = "";
  54.     var $page_title = "";
  55.     var $nav        = array();
  56.     var $html       = "";
  57.     
  58.     var $first      = 0;
  59.     
  60.     var $search_type = 'posts';
  61.     var $sort_order  = 'desc';
  62.     var $sort_key    = 'last_post';
  63.     var $search_in   = 'posts';
  64.     var $prune       = '30';
  65.     var $st_time     = array();
  66.     var $end_time    = array();
  67.     var $st_stamp    = "";
  68.     var $end_stamp   = "";
  69.     
  70.     function Search() {
  71.         global $ibforums, $DB, $std, $print;
  72.         
  73.         if (! $ibforums->vars['allow_search'])
  74.         {
  75.             $std->Error( array( LEVEL => 1, MSG => 'search_off') );
  76.         }
  77.         
  78.         if ($ibforums->member['g_use_search'] != 1)
  79.          {
  80.              $std->Error( array( 'LEVEL' => 1, 'MSG' => 'no_permission' ) );
  81.         }
  82.         
  83.         
  84.         if ($ibforums->input['CODE'] == "") $ibforums->input['CODE'] = '00';
  85.         
  86.         //--------------------------------------------
  87.         // Require the HTML and language modules
  88.         //--------------------------------------------
  89.         
  90.         $ibforums->lang = $std->load_words($ibforums->lang, 'lang_search', $ibforums->lang_id );
  91.         $ibforums->lang = $std->load_words($ibforums->lang, 'lang_forum' , $ibforums->lang_id );
  92.         
  93.         require "./Skin/".$ibforums->skin_id."/skin_search.php";
  94.         
  95.         $this->html = new skin_search();
  96.         
  97.         $this->base_url        = "{$ibforums->vars['board_url']}/index.{$ibforums->vars['php_ext']}?s={$ibforums->session_id}";
  98.         
  99.         if (isset($ibforums->input['st']) )
  100.         {
  101.             $this->first = $ibforums->input['st'];
  102.         }
  103.         
  104.         //--------------------------------------------
  105.         // What to do?
  106.         //--------------------------------------------
  107.         
  108.         if (! isset($ibforums->member['g_use_search']) )
  109.         {
  110.             $std->Error( array( LEVEL => 1, MSG => 'cant_use_feature') );
  111.         }
  112.         
  113.         switch($ibforums->input['CODE']) {
  114.             case '01':
  115.                 $this->do_search();
  116.                 break;
  117.             case '03':
  118.                 $this->get_new_posts();
  119.                 break;
  120.             case 'getactive':
  121.                 $this->get_active();
  122.                 break;
  123.             case 'show':
  124.                 $this->show_results();
  125.                 break;
  126.             default:
  127.                 $this->show_form();
  128.                 break;
  129.         }
  130.         
  131.         // If we have any HTML to print, do so...
  132.         
  133.         $print->add_output("$this->output");
  134.         $print->do_output( array( 'TITLE' => $this->page_title, 'JS' => 0, NAV => $this->nav ) );
  135.             
  136.      }
  137.      
  138.      function show_form() {
  139.          global $DB, $std, $ibforums;
  140.          
  141.          $last_cat_id = -1;
  142.          
  143.          $the_hiddens = "";
  144.         
  145.         $DB->query("SELECT f.id as forum_id, f.name as forum_name, f.position, f.read_perms, c.id as cat_id, c.name as cat_name from ibf_forums f, ibf_categories c where c.id=f.category ORDER BY c.position, f.position");
  146.         
  147.         $forums   = "<select name='forums' class='forminput' onChange='chooseForum()'>\n"
  148.                    ."<option value='all'>>>All open forums";
  149.                    
  150.         $cats     = "<select name='cats' class='forminput' onChange='chooseCat()'>\n"
  151.                    ."<option value='all'>>>All Categories";
  152.         
  153.         while ( $i = $DB->fetch_row() ) {
  154.             if ($last_cat_id != $i['cat_id'])
  155.             {
  156.                 // Print the category
  157.                 $last_cat_id = $i['cat_id'];
  158.                 $cats .= "<option value='{$i['cat_id']}'>{$i['cat_name']}\n";
  159.             }
  160.             
  161.             $selected = "";
  162.             
  163.             if ( isset($ibforums->input['f']) and ($ibforums->input['f'] == $i['forum_id']) )
  164.             {
  165.                 $selected = ' selected';
  166.             }
  167.             
  168.             if ($i['read_perms'] == '*')
  169.             {
  170.                 $forums    .= "<option value=\"{$i['forum_id']}\"$selected>{$i['forum_name']}\n";
  171.             }
  172.             else if (preg_match( "/(^|,)".$ibforums->member['mgroup']."(,|$)/", $i['read_perms']) )
  173.             {
  174.                 $forums .= "<option value='{$i['forum_id']}'$selected>{$i['forum_name']}\n";
  175.             }
  176.             else
  177.             {
  178.                 continue;
  179.             }
  180.         }
  181.         
  182.         $forums .= "</select>";
  183.         $cats   .= "</select>";
  184.         
  185.         $this->output = $this->html->Form($forums, $cats);
  186.         
  187.         $this->page_title = $ibforums->lang['search_title'];
  188.         $this->nav        = array( $ibforums->lang['search_form'] );
  189.         
  190.      }
  191.      
  192.      /******************************************************/
  193.      //
  194.      // Searching is split into two queries. One query to
  195.      // regexp the matches, and pull the topic ID's, the other
  196.      // to pull the data from the topic_id. As topic_id's are indexed
  197.      // the second query shouldn't be too CPU intensive.
  198.      //
  199.      // To find the maximum records that match our criteria to
  200.      // generate the page span, we cap all searches off to '200'
  201.      // results. We then use mysql_num_rows to return the actual
  202.      // number of rows matched, loop over and push the info to 
  203.      // our $topic var until we have 25 results, which is the max.
  204.      // number per page.
  205.      //
  206.      // The other alternative would be to SELECT COUNT(*) then
  207.      // re-query with a 25 LIMIT cap, this of course would be
  208.      // a heavy drain on the SQL engine.
  209.      /******************************************************/
  210.      
  211.  
  212.     function do_search() {
  213.         global $ibforums, $DB, $std, $HTTP_POST_VARS, $print;
  214.         
  215.         //------------------------------------
  216.         // Do we have any input?
  217.         //------------------------------------
  218.         
  219.         if ($ibforums->input['keywords'] == "")
  220.         {
  221.             if ($ibforums->input['namesearch'] != "")
  222.             {
  223.                 $keywords = $this->filter_keywords($ibforums->input['namesearch']);
  224.                 $this->search_type = 'name';
  225.             }
  226.             else if ($ibforums->input['useridsearch'] != "")
  227.             {
  228.                 $keywords = $this->filter_keywords($ibforums->input['useridsearch']);
  229.                 $this->search_type = 'userid';
  230.             }
  231.         }
  232.         else
  233.         {
  234.             $keywords = $this->filter_keywords($ibforums->input['keywords']);
  235.             $this->search_type = 'posts';
  236.         }
  237.         
  238.         //------------------------------------
  239.         
  240.         $check_keywords = trim($keywords);
  241.         
  242.         $check_keywords = str_replace( "%", "", $check_keywords );
  243.         
  244.         if ( (! $check_keywords) or ($check_keywords == "") or (! isset($check_keywords) ) )
  245.         {
  246.             $std->Error( array( 'LEVEL' => 1, 'MSG' => 'no_search_words') );
  247.         }
  248.         
  249.         //------------------------------------
  250.         
  251.         if ($ibforums->input['search_in'] == 'titles')
  252.         {
  253.             $this->search_in = 'titles';
  254.         }
  255.         
  256.         //------------------------------------
  257.         
  258.         $forums = $this->get_searchable_forums();
  259.         
  260.         //------------------------------------
  261.         // Do we have any forums to search in?
  262.         //------------------------------------
  263.         
  264.         if ($forums == "")
  265.         {
  266.             $std->Error( array( 'LEVEL' => 1, 'MSG' => 'no_search_forum') );
  267.         }
  268.     
  269.         //------------------------------------
  270.         
  271.         foreach( array( 'last_post', 'posts', 'starter_name', 'forum_id' ) as $v )
  272.         {
  273.             if ($ibforums->input['sort_key'] == $v)
  274.             {
  275.                 $this->sort_key = $v;
  276.             }
  277.         }
  278.         
  279.         //------------------------------------
  280.         
  281.         foreach ( array( 1, 7, 30, 365, 0 ) as $v )
  282.         {
  283.             if ($ibforums->input['prune'] == $v)
  284.             {
  285.                 $this->prune = $v;
  286.             }
  287.         }
  288.         
  289.         //------------------------------------
  290.         
  291.         if ($ibforums->input['sort_order'] == 'asc')
  292.         {
  293.             $this->sort_order = 'asc';
  294.         }
  295.         
  296.         //------------------------------------
  297.         
  298.         $query = "";
  299.         
  300.         
  301.         if ($this->search_in == 'titles')
  302.         {
  303.             $query = "SELECT DISTINCT(tid) ".
  304.                      "FROM ibf_topics ".
  305.                      "WHERE forum_id IN ($forums) ".
  306.                      "AND approved=1 AND (";
  307.         }
  308.         else
  309.         {
  310.             $query = "SELECT DISTINCT(t.tid) ".
  311.                      "FROM ibf_posts p, ibf_topics t ".
  312.                      "WHERE (t.tid=p.topic_id AND p.forum_id IN ($forums))".
  313.                      " AND (t.approved=1 and p.queued <> 1)".
  314.                      " AND (";
  315.         }
  316.                  
  317.          // Is this a membername search?
  318.          
  319.          if ( ($this->search_type == 'name') or ($this->search_type == 'userid') )
  320.          {
  321.             //------------------------------------------------------------------
  322.             // Get all the possible matches for the supplied name from the DB
  323.             //------------------------------------------------------------------
  324.             
  325.             $keywords = trim( $keywords );
  326.             
  327.             if ($this->search_type == 'name')
  328.             {
  329.                 
  330.                 if ($ibforums->input['exactname'] == 1)
  331.                 {
  332.                     $sql_query = "SELECT id from ibf_members WHERE lower(name)='".$keywords."'";
  333.                 }
  334.                 else
  335.                 {
  336.                     $sql_query = "SELECT id from ibf_members WHERE name like '%".$keywords."%'";
  337.                 }
  338.             }
  339.             else
  340.             {
  341.                 $sql_query = "SELECT id from ibf_members WHERE id='".$keywords."'";
  342.             }
  343.             
  344.             $DB->query( $sql_query );
  345.             $member_string = "";
  346.             
  347.             while ($row = $DB->fetch_row())
  348.             {
  349.                 $member_string .= "'".$row['id']."',";
  350.             }
  351.             
  352.             $member_string = preg_replace( "/,$/", "", $member_string );
  353.             
  354.             // Error out of we matched no members
  355.             
  356.             if ($member_string == "")
  357.             {
  358.                 $std->Error( array( 'LEVEL' => 1, 'MSG' => 'no_search_results') );
  359.             }
  360.             
  361.             //------------------------------------------------------------------
  362.             // If we are still here, append the $query.
  363.             //------------------------------------------------------------------
  364.             
  365.             switch ( $this->search_in ) {
  366.                 case 'posts':
  367.                     $query .= "(p.author_id IN ($member_string) or t.starter_id IN ($member_string))";
  368.                     break;
  369.                 case 'titles':
  370.                     $query .= "starter_id IN ($member_string)";
  371.                     break;
  372.                 default:
  373.                     $query .= "(p.author_id IN ($member_string) or t.starter_id IN ($member_string))";
  374.                     break;
  375.             }
  376.             
  377.             
  378.         }
  379.         else {
  380.             
  381.             //------------------------------------------------------------------
  382.             // Must be a search in posts / topic titles then..
  383.             //------------------------------------------------------------------
  384.             // Start by matching our keywords and pairing them up with a boolean
  385.             // operator if needed.
  386.             //------------------------------------------------------------------
  387.             
  388.             if ($ibforums->input['smethod'] == 'advanced')
  389.             {
  390.                 preg_match_all( "/(^|and|or)\s{1,}(\S+?)\s{1,}/", $keywords, $matches );
  391.                 
  392.                 for ($i = 0 ; $i < count($matches[0]) ; $i++ )
  393.                 {
  394.                     $boolean = $matches[1][$i];
  395.                     $word    = trim($matches[2][$i]);
  396.                     
  397.                     if ( preg_match( "/^%/" , $word ) )
  398.                     {
  399.                         $word = preg_replace( "/^%/", "", $word);
  400.                     }
  401.                     else
  402.                     {
  403.                         $word = '[^0-9a-zA-Z]?'.$word;
  404.                     }
  405.                     
  406.                     if ( preg_match( "/%$/" , $word ) )
  407.                     {
  408.                         $word = preg_replace( "/%$/", "", $word);
  409.                     }
  410.                     else
  411.                     {
  412.                         $word = $word . '[ \t.,!?:;]?';
  413.                     }                
  414.                     
  415.                     if ($boolean)
  416.                     {
  417.                         $boolean = " $boolean";
  418.                     }
  419.                     
  420.                     switch ( $this->search_in )
  421.                     {
  422.                         case 'posts':
  423.                             $query .= "$boolean (LOWER(t.title) REGEXP '$word' or LOWER(p.post) REGEXP '$word') ";
  424.                             break;
  425.                         case 'titles':
  426.                             $query .= "$boolean LOWER(title) REGEXP '$word' ";
  427.                             break;
  428.                         default:
  429.                             $query .= "$boolean (LOWER(t.title) REGEXP '$word' or LOWER(p.post) REGEXP '$word') ";
  430.                             break;
  431.                     }
  432.                 }
  433.             
  434.             }
  435.             else
  436.             {
  437.                 switch ( $this->search_in )
  438.                     {
  439.                         case 'posts':
  440.                             $query .= " (LOWER(t.title) LIKE '%".trim($keywords)."%' or LOWER(p.post) LIKE '%".trim($keywords)."%') ";
  441.                             break;
  442.                         case 'titles':
  443.                             $query .= " LOWER(title) LIKE '%".trim($keywords)."%' ";
  444.                             break;
  445.                         default:
  446.                             $query .= " (LOWER(t.title) LIKE '%".trim($keywords)."%' or LOWER(p.post) LIKE '%".trim($keywords)."%') ";
  447.                             break;
  448.                     }
  449.             }
  450.         }
  451.             
  452.         // Close this WHERE argument...
  453.         
  454.         $query .= ") ";
  455.         
  456.         // Add on the prune days
  457.         
  458.         if ($this->prune > 0)
  459.         {
  460.             $gt_lt = $ibforums->input['prune_type'] == 'older' ? "<" : ">";
  461.             $time = time() - ($ibforums->input['prune'] * 86400);
  462.             
  463.             switch ( $this->search_in )
  464.             {
  465.                 case 'posts':
  466.                     $query .= "AND (t.last_post $gt_lt $time or p.post_date $gt_lt $time)";
  467.                     break;
  468.                 case 'titles':
  469.                     $query .= "AND last_post $gt_lt $time";
  470.                     break;
  471.                 default:
  472.                     $query .= "AND (t.last_post $gt_lt $time or p.post_date $gt_lt $time)";
  473.                     break;
  474.             }
  475.         }
  476.         
  477.         //------------------------------------------------
  478.         // Get the topic ID's to serialize and store into
  479.         // the database
  480.         //------------------------------------------------
  481.         
  482.         $DB->query($query);
  483.     
  484.         $max_hits = $DB->get_num_rows();
  485.     
  486.         $topics = "";
  487.         
  488.         while ($row = $DB->fetch_row() )
  489.         {
  490.             $topics .= $row['tid'].",";
  491.         }
  492.     
  493.         $DB->free_result();
  494.         
  495.         $topics = preg_replace( "/,$/", "", $topics );
  496.         
  497.         //------------------------------------------------
  498.         // Do we have any results?
  499.         //------------------------------------------------
  500.         
  501.         if ($topics == "")
  502.         {
  503.             $std->Error( array( 'LEVEL' => 1, 'MSG' => 'no_search_results' ) );
  504.         }
  505.         
  506.         //------------------------------------------------
  507.         // If we are still here, store the data into the database...
  508.         //------------------------------------------------
  509.         
  510.         $unique_id = md5(uniqid(microtime(),1));
  511.         
  512.         $DB->query("INSERT INTO ibf_search_results (id, topics, search_date, max_hits, sort_key, sort_order) VALUES ('$unique_id', '$topics', '".time()."', '$max_hits', '".$this->sort_key."', '".$this->sort_order."')");
  513.         
  514.         $print->redirect_screen( $ibforums->lang['search_redirect'] , "act=Search&CODE=show&searchid=$unique_id&highlite=".urlencode(trim($keywords)) );
  515.         exit();
  516.         
  517.     }
  518.     
  519.     /******************************************************/
  520.     // Show Results
  521.     // Shows the results of the search
  522.     /******************************************************/
  523.     
  524.     function show_results() {
  525.         global $ibforums, $DB, $std, $HTTP_POST_VARS;
  526.         
  527.         if ( $read = $std->my_getcookie('topicsread') )
  528.         {
  529.             $this->read_array = unserialize(stripslashes($read));
  530.         }
  531.         
  532.         //------------------------------------------------
  533.         // We have a search ID, so lets get the parsed results.
  534.         // Delete old search queries (older than 24 hours)
  535.         //------------------------------------------------
  536.         
  537.         $t_time = time() - (60*60*24);
  538.         
  539.         $DB->query("DELETE FROM ibf_search_results WHERE search_date < '$t_time'");
  540.         
  541.         $unique_id = $ibforums->input['searchid'];
  542.         
  543.         if ($unique_id == "")
  544.         {
  545.             $std->Error( array( 'LEVEL' => 1, 'MSG' => 'no_search_results' ) );
  546.         }
  547.         
  548.         $DB->query("SELECT * FROM ibf_search_results WHERE id='$unique_id'");
  549.         $sr = $DB->fetch_row();
  550.         
  551.         $topics   = $sr['topics'];
  552.         $max_hits = $sr['max_hits'];
  553.         
  554.         $this->sort_order = $sr['sort_order'];
  555.         $this->sort_key   = $sr['sort_key'];
  556.         
  557.         if ($topics == "")
  558.         {
  559.             $std->Error( array( 'LEVEL' => 1, 'MSG' => 'no_search_results' ) );
  560.         }
  561.         
  562.         $url_words = $this->convert_highlite_words($ibforums->input['highlite']);
  563.         
  564.         $links = $std->build_pagelinks( array( TOTAL_POSS  => $max_hits,
  565.                                                PER_PAGE    => 25,
  566.                                                CUR_ST_VAL  => $this->first,
  567.                                                L_SINGLE    => "",
  568.                                                L_MULTI     => $ibforums->lang['search_pages'],
  569.                                                BASE_URL    => $this->base_url."&act=Search&CODE=show&searchid=$unique_id&hl=".$url_words,
  570.                                              )
  571.                                       );
  572.                                       
  573.         
  574.         
  575.         $this->output .= $this->html->start( array( 'SHOW_PAGES' => $links ) );
  576.         
  577.         $DB->query("SELECT t.*, f.id as forum_id, f.name as forum_name FROM ibf_topics t, ibf_forums f WHERE t.tid IN($topics) and f.id=t.forum_id ORDER BY ".$this->sort_key." ".$this->sort_order." LIMIT ".$this->first.",25");
  578.         
  579.         while ( $row = $DB->fetch_row() )
  580.         {
  581.             $row['keywords'] = $url_words;
  582.             $this->output .= $this->html->RenderRow( $this->parse_entry($row) );
  583.         
  584.         }
  585.         
  586.         $this->page_title = $ibforums->lang['search_results'];
  587.         $this->nav        = array( "<a href='{$this->base_url}&act=Search'>{$ibforums->lang['search_form']}</a>", $ibforums->lang['search_title'] );
  588.         
  589.         $this->output .= $this->html->end(array( 'SHOW_PAGES' => $links ));
  590.         
  591.     }
  592.  
  593.     /******************************************************/
  594.     // Get active
  595.     // Show all topics posted in / created between a user
  596.     // definable amount of days..
  597.     /******************************************************/
  598.     
  599.     function get_active() {
  600.         global $ibforums, $DB, $std, $HTTP_POST_VARS;
  601.         
  602.         
  603.         //------------------------------------
  604.         // If we don't have a search ID (searchid)
  605.         // then it's a fresh query.
  606.         //
  607.         //------------------------------------
  608.         
  609.         if (! isset($ibforums->input['searchid']) )
  610.         {
  611.         
  612.             //------------------------------------
  613.             // Do we have any start date input?
  614.             //------------------------------------
  615.             
  616.             if ($ibforums->input['st_day'] == "")
  617.             {
  618.                 // No? Lets work out the start date as 24hrs ago
  619.                 $ibforums->input['st_day'] = 1;
  620.                 $this->st_stamp = time() - (60*60*24);
  621.                 
  622.             }
  623.             else
  624.             {
  625.                 $ibforums->input['st_day'] = preg_replace( "/s/", "", $ibforums->input['st_day']);
  626.                 $this->st_stamp = time() - (60*60*24*$ibforums->input['st_day']);
  627.             }
  628.             
  629.             
  630.             //------------------------------------
  631.             // Do we have any END date input?
  632.             //------------------------------------
  633.             
  634.             if ($ibforums->input['end_day'] == "")
  635.             {
  636.                 // No? Lets work out the end date as now
  637.                 
  638.                 $this->end_stamp = time();
  639.                 $ibforums->input['end_day'] = 0;
  640.                 
  641.             }
  642.             else
  643.             {
  644.                 $ibforums->input['end_day'] = preg_replace( "/e/", "", $ibforums->input['end_day']);
  645.                 $this->end_stamp = time() - (60*60*24*$ibforums->input['end_day']);
  646.             }
  647.             
  648.             
  649.             //------------------------------------
  650.             // Synchronise our input data
  651.             //------------------------------------
  652.             
  653.             $ibforums->input['cat_forum'] = 'cat';
  654.             $ibforums->input['cats']      = 'all';
  655.             
  656.             $forums = $this->get_searchable_forums();
  657.             
  658.             //------------------------------------
  659.             // Do we have any forums to search in?
  660.             //------------------------------------
  661.             
  662.             if ($forums == "")
  663.             {
  664.                 $std->Error( array( 'LEVEL' => 1, 'MSG' => 'no_search_forum') );
  665.             }
  666.         
  667.             
  668.             
  669.             $query = "SELECT DISTINCT(t.tid) FROM ibf_posts p, ibf_topics t WHERE p.post_date < ".$this->end_stamp." AND p.post_date > ".$this->st_stamp." AND p.forum_id IN($forums) and p.topic_id=t.tid ORDER BY t.last_post DESC LIMIT 0,200";
  670.             
  671.             //------------------------------------------------
  672.             // Get the topic ID's to serialize and store into
  673.             // the database
  674.             //------------------------------------------------
  675.             
  676.             $DB->query($query);
  677.         
  678.             $max_hits = $DB->get_num_rows();
  679.         
  680.             $topics = "";
  681.             
  682.             while ($row = $DB->fetch_row() )
  683.             {
  684.                 $topics .= $row['tid'].",";
  685.             }
  686.         
  687.             $DB->free_result();
  688.             
  689.             $topics = preg_replace( "/,$/", "", $topics );
  690.             
  691.             //------------------------------------------------
  692.             // Do we have any results?
  693.             //------------------------------------------------
  694.             
  695.             if ($topics == "")
  696.             {
  697.                 $this->output .= $this->html->active_start( array( 'SHOW_PAGES' => "" ) );
  698.                 $this->output .= $this->html->active_none();
  699.                 $this->output .= $this->html->end("");
  700.                 $this->page_title = $ibforums->lang['search_results'];
  701.                 $this->nav        = array( "<a href='{$this->base_url}&act=Search'>{$ibforums->lang['search_form']}</a>", $ibforums->lang['search_title'] );
  702.                 return ""; // return empty handed
  703.             }
  704.             
  705.             //------------------------------------------------
  706.             // If we are still here, store the data into the database...
  707.             //------------------------------------------------
  708.             
  709.             $unique_id = md5(uniqid(microtime(),1));
  710.             
  711.             $DB->query("INSERT INTO ibf_search_results (id, topics, search_date, max_hits, sort_key, sort_order) VALUES ('$unique_id', '$topics', '".time()."', '$max_hits', '".$this->sort_key."', '".$this->sort_order."')");
  712.             
  713.         }
  714.         else 
  715.         {
  716.             //------------------------------------------------
  717.             // We have a search ID, so lets get the parsed results.
  718.             // Delete old search queries (older than 24 hours)
  719.             //------------------------------------------------
  720.             
  721.             $t_time = time() - (60*60*24);
  722.             
  723.             $DB->query("DELETE FROM ibf_search_results WHERE search_date < '$t_time'");
  724.             
  725.             $unique_id = $ibforums->input['searchid'];
  726.             
  727.             $DB->query("SELECT * FROM ibf_search_results WHERE id='$unique_id'");
  728.             $sr = $DB->fetch_row();
  729.             
  730.             $topics   = $sr['topics'];
  731.             $max_hits = $sr['max_hits'];
  732.             
  733.             $this->sort_order = $sr['sort_order'];
  734.             $this->sort_key   = $sr['sort_key'];
  735.             
  736.             if ($topics == "")
  737.             {
  738.                 $std->Error( array( 'LEVEL' => 1, 'MSG' => 'no_search_results' ) );
  739.             }
  740.         }
  741.         
  742.         // Our variables are centralised, lets get the array slice depending on our $this->first
  743.         // position.
  744.         
  745.         // How cool is this? ;)
  746.         
  747.         $topic_string = implode( "," , array_slice( explode(",",$topics), $this->first, 25 ) );
  748.         
  749.         // That splits the string into an array by a comma, gets a slice depending on our limit,
  750.         // say 0 to 25 and then joins the array into a string seperated by commas, all in one
  751.         // line :D
  752.             
  753.         $url_words = urlencode(trim($keywords));
  754.             
  755.         $links = $std->build_pagelinks( array( TOTAL_POSS  => $max_hits,
  756.                                                PER_PAGE    => 25,
  757.                                                CUR_ST_VAL  => $this->first,
  758.                                                L_SINGLE    => "",
  759.                                                L_MULTI     => "",
  760.                                                BASE_URL    => $this->base_url."&act=Search&CODE=getactive&searchid=$unique_id",
  761.                                              )
  762.                                       );
  763.                                       
  764.         
  765.         
  766.         $this->output .= $this->html->active_start( array( 'SHOW_PAGES' => $links ) );
  767.         
  768.         // Regex in our selected values.
  769.         
  770.         $this->output = preg_replace( "/(<option value='s".$ibforums->input['st_day']."')/" , "\\1 selected", $this->output );
  771.         $this->output = preg_replace( "/(<option value='e".$ibforums->input['end_day']."')/", "\\1 selected", $this->output );
  772.         
  773.         $DB->query("SELECT t.*, f.id as forum_id, f.name as forum_name FROM ibf_topics t, ibf_forums f WHERE t.tid IN($topic_string) and f.id=t.forum_id ORDER BY ".$this->sort_key." ".$this->sort_order." LIMIT 0,25");
  774.         
  775.         while ( $row = $DB->fetch_row() )
  776.         {
  777.             $row['keywords'] = $url_words;
  778.             $this->output .= $this->html->RenderRow( $this->parse_entry($row) );
  779.         
  780.         }
  781.         
  782.         $this->page_title = $ibforums->lang['search_results'];
  783.         $this->nav        = array( "<a href='{$this->base_url}&act=Search'>{$ibforums->lang['search_form']}</a>", $ibforums->lang['search_title'] );
  784.         
  785.         $this->output .= $this->html->end("");
  786.         
  787.     }
  788.     
  789.     
  790.     
  791.     
  792.     
  793.     function parse_entry($topic) {
  794.         global $DB, $std, $ibforums;
  795.         
  796.         $topic['last_text']   = $ibforums->lang[last_post_by];
  797.         
  798.         $topic['last_poster'] = ($topic['last_poster_id'] != 0)
  799.                                 ? "<b><a href='{$this->base_url}&act=Profile&CODE=03&MID={$topic['last_poster_id']}'>{$topic['last_poster_name']}</a></b>"
  800.                                 : "-".$topic['last_poster_name']."-";
  801.                                 
  802.         $topic['starter']     = ($topic['starter_id']     != 0)
  803.                                 ? "<a href='{$this->base_url}&act=Profile&CODE=03&MID={$topic['starter_id']}'>{$topic['starter_name']}</a>"
  804.                                 : "-".$topic['starter_name']."-";
  805.      
  806.         if ($topic['poll_state'])
  807.         {
  808.             $topic['prefix']     = $ibforums->vars['pre_polls'].' ';
  809.         }
  810.     
  811.         $topic['folder_img']     = $std->folder_icon($topic);
  812.         
  813.         $topic['topic_icon']     = $topic['icon_id']  ? '<img src="'.$ibforums->vars['img_url'] . '/icon' . $topic['icon_id'] . '.gif" border="0" alt="">'
  814.                                                       : ' ';
  815.                                                               
  816.         if ($topic['pinned'])
  817.         {
  818.             $topic['topic_icon']       = $ibforums->skin['B_PIN'];
  819.         }
  820.         
  821.         $topic['topic_start_date'] = $std->get_date( $topic['start_date'], 'LONG' );
  822.     
  823.     
  824.         $pages = 1;
  825.         
  826.         if ($topic['posts'])
  827.         {
  828.             if ( (($topic['posts'] + 1) % $ibforums->vars['display_max_posts']) == 0 )
  829.             {
  830.                 $pages = ($topic['posts'] + 1) / $ibforums->vars['display_max_posts'];
  831.             }
  832.             else
  833.             {
  834.                 $number = ( ($topic['posts'] + 1) / $ibforums->vars['display_max_posts'] );
  835.                 $pages = ceil( $number);
  836.             }
  837.             
  838.         }
  839.         
  840.         if ($pages > 1)
  841.         {
  842.             $topic['PAGES'] = "<span id='small'>({$ibforums->lang['topic_sp_pages']} ";
  843.             for ($i = 0 ; $i < $pages ; ++$i ) {
  844.                 $real_no = $i * $ibforums->vars['display_max_posts'];
  845.                 $page_no = $i + 1;
  846.                 if ($page_no == 4) {
  847.                     $topic['PAGES'] .= "<a href='{$this->base_url}&act=ST&f={$topic['forum_id']}&t={$topic['tid']}&st=" . ($pages - 1) * $ibforums->vars['display_max_posts'] . "&hl={$topic['keywords']}'>...$pages </a>";
  848.                     break;
  849.                 } else {
  850.                     $topic['PAGES'] .= "<a href='{$this->base_url}&act=ST&f={$topic['forum_id']}&t={$topic['tid']}&st=$real_no&hl={$topic['keywords']}'>$page_no </a>";
  851.                 }
  852.             }
  853.             $topic['PAGES'] .= ")</span>";
  854.         }
  855.         
  856.         if ($topic['posts'] < 0) $topic['posts'] = 0;
  857.         
  858.         $last_time = $this->read_array[ $topic['tid'] ] > $ibforums->input['last_visit'] ? $this->read_array[ $topic['tid'] ] : $ibforums->input['last_visit'];
  859.         
  860.         if ($last_time  && ($topic['last_post'] > $last_time))
  861.         {
  862.             $topic['go_last_page'] = "<a href='{$this->base_url}&act=ST&f={$topic['forum_id']}&t={$topic['tid']}&view=getlastpost'>" . $ibforums->skin['GO_LAST_ON'] . "</a>";
  863.             $topic['go_new_post']  = "<a href='{$this->base_url}&act=ST&f={$topic['forum_id']}&t={$topic['tid']}&view=getnewpost'>"  . $ibforums->skin['NEW_POST']   . "</a>";
  864.         
  865.         }
  866.         else
  867.         {
  868.             $topic['go_last_page'] = "<a href='{$this->base_url}&act=ST&f={$topic['forum_id']}&t={$topic['tid']}&view=getlastpost'>" . $ibforums->skin['GO_LAST_OFF'] . "</a>";
  869.             $topic['go_new_post']  = "";
  870.         }
  871.         
  872.         // Do the quick goto last page icon stuff
  873.         
  874.         $maxpages = ($pages - 1) * $ibforums->vars['display_max_posts'];
  875.         if ($maxpages < 0) $maxpages = 0;
  876.         
  877.         $topic['last_post']  = $std->get_date($topic['last_post'], 'LONG');
  878.             
  879.         if ($topic['state'] == 'link')
  880.         {
  881.             $t_array = explode("&", $topic['moved_to']);
  882.             $topic['tid']       = $t_array[0];
  883.             $topic['forum_id']  = $t_array[1];
  884.             $topic['title']     = $topic['title'];
  885.             $topic['views']     = '--';
  886.             $topic['posts']     = '--';
  887.             $topic['prefix']    = $ibforums->vars['pre_moved']." ";
  888.             $topic['go_new_post'] = "";
  889.         }
  890.         
  891.         if ($topic['pinned'] == 1)
  892.         {
  893.             $topic['prefix']     = $ibforums->vars['pre_pinned'];
  894.             $topic['topic_icon'] = $ibforums->skin['B_PIN'];
  895.             
  896.         }
  897.           
  898.         return $topic;
  899.     }
  900.         
  901.      
  902.         
  903.     function filter_keywords($words="") {
  904.     
  905.         // force to lowercase and swop % into a safer version
  906.         
  907.         $words = trim( strtolower( str_replace( "%", "\\%", $words) ) );
  908.         
  909.         // Remove trailing boolean operators
  910.         
  911.         $words = preg_replace( "/\s+(and|or)$/" , "" , $words );
  912.         
  913.         // Swop wildcard into *SQL percent
  914.         
  915.         $words = str_replace( "*", "%", $words );
  916.         
  917.         // Make safe underscores
  918.         
  919.         $words = str_replace( "_", "\\_", $words );
  920.         
  921.         // Remove crap
  922.         
  923.         $words = preg_replace( "/[\|\[\]\{\}\(\)\.,:;\?\-\+\#\\\\\/\"']/", "", $words );
  924.         
  925.         return " ".preg_quote($words)." ";
  926.     
  927.     }
  928.         
  929.     
  930.     //------------------------------------------------------
  931.     // Make the hl words nice and stuff
  932.     //------------------------------------------------------
  933.     
  934.     function convert_highlite_words($words="")
  935.     {
  936.         $words = trim(urldecode($words));
  937.         
  938.         // Convert booleans to something easy to match next time around
  939.         
  940.         $words = preg_replace("/\s+(and|or)(\s+|$)/i", ",\\1,", $words);
  941.         
  942.         // Convert spaces to plus signs
  943.         
  944.         $words = preg_replace("/\s/", "+", $words);
  945.         
  946.         return $words;
  947.     }
  948.         
  949.     //------------------------------------------------------
  950.     // Get the searchable forums
  951.     //------------------------------------------------------    
  952.         
  953.     function get_searchable_forums() {
  954.         global $ibforums, $DB, $std, $HTTP_POST_VARS;
  955.         
  956.         $forum_array  = array();
  957.         $forum_string = "";
  958.         $sql_query    = "";
  959.         // If we have an array of "forums", loop
  960.         // through and build our *SQL IN( ) statement.
  961.         
  962.         
  963.         // Are we looking for cats or forums..
  964.         
  965.         if ($ibforums->input['cat_forum'] == 'cat')
  966.         {
  967.             if ($ibforums->input['cats'] == 'all')
  968.             {
  969.                 $sql_query = "SELECT id, read_perms, password from ibf_forums";
  970.             } 
  971.             else
  972.             {
  973.                 if (! preg_match( "/^(?:\d+)$/", $ibforums->input['cats'] ) )
  974.                 {
  975.                     return;
  976.                 }
  977.                 else
  978.                 {
  979.                     $sql_query = "SELECT id, read_perms, password from ibf_forums WHERE category='".$ibforums->input['cats']."'";
  980.                 }
  981.             }
  982.         }
  983.         else
  984.         {
  985.             if ($ibforums->input['forums'] == 'all')
  986.             {
  987.                 $sql_query = "SELECT id, read_perms, password from ibf_forums";
  988.             }
  989.             else
  990.             {
  991.                 if (! preg_match( "/^(?:\d+)$/", $ibforums->input['forums'] ) )
  992.                 {
  993.                     return;
  994.                 }
  995.                 else
  996.                 {
  997.                     $sql_query = "SELECT id, read_perms, password from ibf_forums WHERE id='".$ibforums->input['forums']."'";
  998.                 }
  999.             }
  1000.         }
  1001.         
  1002.         if ($sql_query != "")
  1003.         {
  1004.             $DB->query( $sql_query );
  1005.             
  1006.             while ($i = $DB->fetch_row())
  1007.             {
  1008.                 $pass = 1;
  1009.                 
  1010.                 if ($i['password'] != "")
  1011.                 {
  1012.                     if ( ! $c_pass = $std->my_getcookie('iBForum'.$i['id']) )
  1013.                     {
  1014.                         $pass = 0;
  1015.                     }
  1016.                 
  1017.                     if ( $c_pass == $i['password'] )
  1018.                     {
  1019.                         $pass = 1;
  1020.                     }
  1021.                 }
  1022.                 
  1023.                 if ($pass == 1)
  1024.                 {
  1025.                     if ($i['read_perms'] == '*')
  1026.                     {
  1027.                         $forum_array[] = $i['id'];
  1028.                     }
  1029.                     else if ( preg_match( "/(^|,)".$ibforums->member['mgroup']."(,|$)/", $i['read_perms']) )
  1030.                     {
  1031.                         $forum_array[] = $i['id'];
  1032.                     }
  1033.                 }
  1034.             }
  1035.         }
  1036.                         
  1037.         $forum_string = implode( "," , $forum_array );
  1038.         
  1039.         return $forum_string;
  1040.         
  1041.     }
  1042.         
  1043.         
  1044.         
  1045.         
  1046.         
  1047. }
  1048.  
  1049. ?>
  1050.